package com.sugree.jibjib.data;

import java.util.Date;
import java.util.List;
import java.util.ArrayList;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import android.database.Cursor;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.Html;
import android.util.Log;

import com.sugree.jibjib.data.JibJibDatabase.Tweets;
import com.sugree.jibjib.data.JibJibDatabase.DirectMessages;

public class Tweet implements Parcelable {
	private static final String TAG = "Tweet";

	public static final String AT_REGEXP = "(\\s|\\A)@(\\w+)";
	public static final String LINK_REGEXP = "https?://(www\\.)?((twitpic\\.com|twitgoo\\.com|img\\.ly|yfrog\\.com|flic\\.kr/p)/[a-zA-Z0-9]+|tweetphoto\\.com/[0-9]+)";

	protected String mUsername;
	protected long mId;
	protected String mText;
	protected String mScreenName;
	protected String mSource;
	protected long mToStatusId;
	protected String mToScreenName;
	protected boolean mFavorited;
	protected boolean mProtected;
	protected boolean mMentioned;
	protected long mCreatedDate;
	protected long mSentDate;
	protected String mLocation;

	public Tweet() {
	}

	public Tweet(long id, String username, String screenName, String text, String location) {
		this.mId = id;
		this.mUsername = username;
		this.mScreenName = screenName;
		this.mText = text;
		this.mLocation = location;
	}

	public Tweet(String username, String screenName, String text) {
		this.mId = 0;
		this.mUsername = username;
		this.mScreenName = screenName;
		this.mText = text;
	}

	public static Tweet fetchOneTweet(String username, JSONObject j) throws JSONException {
		Tweet o = new Tweet();
		o.mUsername = username;
		o.mId = j.getLong("id");
		o.mText = Html.fromHtml(j.getString("text")).toString();
		JSONObject u = j.getJSONObject("user");
		o.mScreenName = u.getString("screen_name");
		o.mSource = j.getString("source");
		if (!j.isNull("in_reply_to_status_id")) {
			o.mToStatusId = j.getLong("in_reply_to_status_id");
			o.mToScreenName = j.getString("in_reply_to_screen_name");
		} else {
			o.mToStatusId = 0;
			o.mToScreenName = null;
		}
		o.mFavorited = j.getBoolean("favorited");
		o.mProtected = u.getBoolean("protected");
		o.mCreatedDate = Date.parse(j.getString("created_at"));
		o.mSentDate = o.mCreatedDate;
		try {
			JSONArray coords = j.getJSONObject("geo").getJSONArray("coordinates");
			o.mLocation =
				Location.convert(coords.getDouble(0), Location.FORMAT_DEGREES)+","+
				Location.convert(coords.getDouble(1), Location.FORMAT_DEGREES);
		} catch (JSONException e) {
			o.mLocation = null;
		}
		return o;
	}

	public static Tweet fetchOneTweet(String username, Cursor c) {
		Tweet o =  new Tweet();
		o.mUsername = username;
		o.mId = c.getLong(c.getColumnIndex(Tweets._ID));
		o.mText = c.getString(c.getColumnIndex(Tweets.MESSAGE));
		o.mScreenName = c.getString(c.getColumnIndex(Tweets.AUTHOR_ID));
		o.mSource = c.getString(c.getColumnIndex(Tweets.SOURCE));
		if (!c.isNull(c.getColumnIndex(Tweets.IN_REPLY_TO_STATUS_ID))) {
			o.mToStatusId = c.getLong(c.getColumnIndex(Tweets.IN_REPLY_TO_STATUS_ID));
			o.mToScreenName = c.getString(c.getColumnIndex(Tweets.IN_REPLY_TO_AUTHOR_ID));
		} else {
			o.mToStatusId = 0;
			o.mToScreenName = null;
		}
		o.mFavorited = c.getString(c.getColumnIndex(Tweets.FAVORITED)).equals("1");
		o.mProtected = c.getString(c.getColumnIndex(Tweets.PROTECTED)).equals("1");
		o.mCreatedDate = c.getLong(c.getColumnIndex(Tweets.CREATED_DATE));
		o.mSentDate = c.getLong(c.getColumnIndex(Tweets.SENT_DATE));
		if (!c.isNull(c.getColumnIndex(Tweets.LATITUDE))) {
			o.mLocation = Location.convert(c.getDouble(c.getColumnIndex(Tweets.LATITUDE)), Location.FORMAT_DEGREES)+","+
				Location.convert(c.getDouble(c.getColumnIndex(Tweets.LONGITUDE)), Location.FORMAT_DEGREES);
		} else {
			o.mLocation = null;
		}
		return o;
	}

	public static List<Tweet> fetchAllTweets(String username, Cursor c) {
		List<Tweet> ret = new ArrayList<Tweet>();

		while (c.moveToNext()) {
			ret.add(fetchOneTweet(username, c));
		}

		return ret;
	}

	public static Tweet fetchOneMessage(String username, Cursor c) {
		Tweet o =  new Tweet();
		o.mUsername = username;
		o.mId = c.getLong(c.getColumnIndex(DirectMessages._ID));
		o.mText = c.getString(c.getColumnIndex(DirectMessages.MESSAGE));
		o.mScreenName = c.getString(c.getColumnIndex(DirectMessages.AUTHOR_ID));
		o.mProtected = c.getString(c.getColumnIndex(DirectMessages.PROTECTED)).equals("1");
		o.mCreatedDate = c.getLong(c.getColumnIndex(DirectMessages.CREATED_DATE));
		o.mSentDate = c.getLong(c.getColumnIndex(DirectMessages.SENT_DATE));

		return o;
	}

	public static List<Tweet> fetchAllMessages(String username, Cursor c) {
		List<Tweet> ret = new ArrayList<Tweet>();

		while (c.moveToNext()) {
			ret.add(fetchOneMessage(username, c));
		}

		return ret;
	}

	public String replyDirectMessage() {
		return "d "+mScreenName+" ";
	}

	public String reply() {
		return "@"+mScreenName+" "+getLinks();
	}

	public String replyQuote() {
		return "@"+mScreenName+" "+mText+" ";
	}

	public String retweet() {
		return "RT @"+mScreenName+": "+mText;
	}

	public String replyAll() {
		return getMentions("@"+mScreenName+" ")+getLinks();
	}

	public String getMentions(String t) {
		StringBuffer s = new StringBuffer(t);
		String u = mUsername.toLowerCase();
		Pattern p = Pattern.compile(AT_REGEXP);
		Matcher m = p.matcher(mText);
		while (m.find()) {
			String a = "@"+m.group(2)+" ";
			if (!m.group(2).toLowerCase().equals(u) &&
					!s.toString().toLowerCase().contains(a.toLowerCase())) {
				s.append(a);
			}
		}
		return s.toString();
	}

	public String getLinks() {
		StringBuffer s = new StringBuffer();
		Pattern p = Pattern.compile(LINK_REGEXP);
		Matcher m = p.matcher(mText);
		while (m.find()) {
			s.append(m.group(0)+" ");
		}
		return s.toString();
	}

	public String getUsername() {
		return mUsername;
	}

	public long getId() {
		return mId;
	}

	public String getText() {
		return mText;
	}

	public String getScreenName() {
		return mScreenName;
	}

	public String getSource() {
		return mSource;
	}

	public long getToStatusId() {
		return mToStatusId;
	}

	public String getToScreenName() {
		return mToScreenName;
	}

	public boolean getFavorited() {
		return mFavorited;
	}

	public boolean getProtected() {
		return mProtected;
	}

	public long getCreatedDate() {
		return mCreatedDate;
	}

	public long getSentDate() {
		return mSentDate;
	}

	public String getLocation() {
		return mLocation;
	}

	@Override
	public String toString() {
		return String.format("@%s: %s", mScreenName, mText);
	}

	public int describeContents() {
		return 0;
	}

	public static final Parcelable.Creator<Tweet> CREATOR = new Parcelable.Creator<Tweet>() {
		public Tweet createFromParcel(Parcel in) {
			return new Tweet(in);
		}

		public Tweet[] newArray(int size) {
			return new Tweet[size];
		}
	};

	private Tweet(Parcel in) {
		readFromParcel(in);
	}

	public void writeToParcel(Parcel out, int flags) {
		out.writeString(mUsername);
		out.writeLong(mId);
		out.writeString(mText);
		out.writeString(mScreenName);
		out.writeString(mSource);
		out.writeLong(mToStatusId);
		out.writeString(mToScreenName);
		boolean[] bool = new boolean[2];
		bool[0] = mFavorited;
		bool[1] = mProtected;
		out.writeBooleanArray(bool);
		out.writeLong(mCreatedDate);
		out.writeLong(mSentDate);
		out.writeString(mLocation);
	}

	public void readFromParcel(Parcel in) {
		mUsername = in.readString();
		mId = in.readLong();
		mText = in.readString();
		mScreenName = in.readString();
		mSource = in.readString();
		mToStatusId = in.readLong();
		mToScreenName = in.readString();
		boolean[] bool = new boolean[2];
		in.readBooleanArray(bool);
		mFavorited = bool[0];
		mProtected = bool[1];
		mCreatedDate = in.readLong();
		mSentDate = in.readLong();
		mLocation = in.readString();
	}
}
